home *** CD-ROM | disk | FTP | other *** search
/ Trading on the Edge / Trading On The Edge - CD-ROM Toolkit (Wayzata Technology)(2031)(1994).bin / mac / Shared / AZTE programs / human.c < prev    next >
Text File  |  1993-06-11  |  33KB  |  1,521 lines

  1. /* 10/24/89.
  2.  * Human player for the Double Oral Auction Tournament.
  3.  * C version.        R.G. Palmer, Jan-Apr 1989.
  4.  * 
  5.  * This is based on the standard C skeleton player, but asks the user
  6.  * what to do at each stage.  It also has help facilities and options
  7.  * to display past history etc.
  8.  *
  9.  * This must be linked with the result of compiling the control routines
  10.  * in control.c.  You must customize the definitions in the define.h
  11.  * header file AND the definitions below before compiling.
  12.  *
  13.  * See README for compilation instructions.
  14.  *
  15.  *---------------History mechanism------------------------------------
  16.  * HISTORY may be defined to enable the 'history' mechanism for a
  17.  * human player.
  18.  * The history mechanism is accessed by typing h at a prompt and
  19.  * produces a display of the recent history of the game.
  20.  * It uses extra memory, and extra I/O time if FILEBASED.
  21.  *
  22.  * MAXHIST specifies how far back the history should be kept.  Use 3
  23.  * less than the number of screen lines on a non-scrollable terminal.
  24.  * The extra memory and I/O time increase for larger MAXHIST.
  25.  *
  26.  * Define AUTOHIST to be the number of lines of  history to be shown
  27.  * automatically at each step.  Set to 0 for none.  Use up to 7 less
  28.  * than the number of screen lines on a non-scrollable terminal.
  29.  *
  30.  * MAXHIST and AUTOHIST are ignored if HISTORY is not set.  13 and 9
  31.  * are recommended for a Macintosh with Lightspeed C 4.0.
  32.  */
  33.  
  34. #define HISTORY        1
  35. #define MAXHIST     21
  36. #define AUTOHIST    0
  37.  
  38. /*---------------Timeout and '.' display------------------------------
  39.  * Define TIMEOUT for a human player if you want the program to default
  40.  * your replies if you don't respond within a certain time.  The default
  41.  * is equivalent to you just pressing RETURN.  The time allowed is
  42.  * approximately 2/3 of the monitor's 'timeout' value (read from the game
  43.  * file).  The user can turn the timeout mechanism off or on with the w and
  44.  * -w commands.
  45.  *
  46.  * Define DOTS if you want dots (.) to be displayed every second during
  47.  * the waiting period, with colons (:) in the last five seconds.
  48.  *
  49.  * Define INTRCHAR to be the integer value of your interrupt character.
  50.  * If TIMEOUT is defined, your program has to do its own interrupt
  51.  * processing because a raw mode read is used.  Common values include
  52.  * 3 for cntl-C, 24 for cntl-X, 25 for cntl-Y, and 127 for DEL.
  53.  * If you don't define it a default value will be used (cntl-C for
  54.  * most systems, '.' for Macintosh).
  55.  *
  56.  * If you don't define TIMEOUT, the timeout mechanism will be disabled
  57.  * and w and -w will have no effect.  DOTS is then ignored.
  58.  * It may be worth trying this case if you have compilation or run-time
  59.  * problems associated with the non-blocking I/O used for input when
  60.  * TIMEOUT is defined.
  61.  
  62.  * If the timeout mechanism is disabled (either by not defining TIMEOUT
  63.  * or with the w command), the monitor may timeout the player and send
  64.  * a **late** message next time it does respond.
  65.  *
  66.  * If you define TIME_OUT_BO and TIME_OUT_BS, the computer will use
  67.  * these values for timing out during the bid/offer and buy/sell steps,
  68.  * respectively, instead of 2/3 of the monitor's timeout value.
  69.  */
  70.  
  71. #define TIMEOUT        1
  72. #define DOTS        1
  73.  
  74. #define TIME_OUT_BO 10
  75. #define TIME_OUT_BS 10
  76.  
  77. /*---------------Period notification----------------------------------
  78.  * Define BEEP if you want to be notified of the start of each period
  79.  * with a BEEP.  This is particularly useful with multiple human players,
  80.  * when there may be a long period between the time that YOU can't make
  81.  * any more trades in a period and the actual end of that period.
  82.  */
  83.  
  84. #define BEEP    1
  85.  
  86. /*---------------Headings--------------------------------------------
  87.  * Define HEADLINE if you want the time and token information to appear
  88.  * before buy-sell steps as well as bid-offer steps.  Useful if you
  89.  * set AUTOHIST > 0, or if your screen gets cleared on every step.
  90.  */
  91.  
  92. /* #define HEADLINE    1 */
  93.  
  94. /* ---------------------- end of customization ------------------------- */
  95.  
  96. #include "define.h"
  97. #include <stdio.h>
  98. #ifdef THINKC3
  99. #include <strings.h>
  100. #else
  101. #include <strings.h>
  102. #endif
  103.  
  104.  
  105. /* List of global variables */
  106. extern int nplayers;
  107. extern int nbuyers;
  108. extern int nsellers;
  109. extern int bnumber[];
  110. extern int snumber[];
  111. extern int nrounds;
  112. extern int nperiods;
  113. extern int ntimes;
  114. extern int minprice;
  115. extern int maxprice;
  116. extern int gameid;
  117. extern int r;
  118. extern int p;
  119. extern int t;
  120. extern int cbid;
  121. extern int coffer;
  122. extern int bidder;
  123. extern int offerer;
  124. extern int nbids;
  125. extern int noffers;
  126. extern int bids[];
  127. extern int offers[];
  128. extern int bstype;
  129. extern int price;
  130. extern int buyer;
  131. extern int seller;
  132. extern int btrades[];
  133. extern int strades[];
  134. extern int ntrades;
  135. extern int prices[];
  136. extern int lasttime;
  137. extern int id;
  138. extern int role;
  139. extern int timeout;
  140. extern int ntokens;
  141. extern int token[];
  142. extern int mytrades;
  143. extern int mylasttime;
  144. extern int pprofit;
  145. extern int rprofit;
  146. extern int gprofit;
  147. extern int nobidoff;
  148. extern int bo;
  149. extern int nobuysell;
  150. extern int bs;
  151. extern int late;
  152. extern int tradelist[];
  153. extern int profitlist[];
  154. extern int efficiency;
  155.  
  156. extern int noblock;
  157.  
  158. extern int waitforreturn;
  159.  
  160. int hmtype = 1;            /* human player */
  161.  
  162. extern void error();
  163. extern double drand();
  164. extern void twolinehead(),showcurrent(),showprices(),nl();
  165.  
  166. /* system dependent includes, defines, etc. */
  167. #ifndef DISPLAY
  168.     <<DISPLAY not defined>>
  169. #endif
  170.  
  171. /* generic */
  172. #ifdef UNIX
  173. #define TERMIO    1
  174. #endif
  175.  
  176. #ifdef BSD43
  177. #define UNIX 1
  178. #define TTY    1
  179. #define FCNTL    1
  180. #endif
  181.  
  182. #ifdef SUN3
  183. #define UNIX 1
  184. char * sprintf();    /* for lint */
  185. #define TTY    1
  186. #define FCNTL    1
  187. #endif
  188.  
  189. #ifdef SUN4
  190. #define UNIX 1
  191. char * sprintf();    /* for lint */
  192. #define TERMIOS    1
  193. #endif
  194.  
  195. #ifdef CRAY
  196. #define UNIX 1
  197. #define TERMIO    1
  198. #define FCNTL    1
  199. #endif
  200.  
  201. #ifdef IRIS
  202. #define UNIX 1
  203. #define TERMIO    1
  204. #endif
  205.  
  206. #ifdef TURBOC
  207. #define MSDOS 1
  208. #define DOS_OR_T3 1
  209. #define ANSI  1
  210. #endif
  211.  
  212. #ifdef QUICKC
  213. #define MSDOS 1
  214. #define DOS_OR_T3 1
  215. #define ANSI  1
  216. #include <time.h>
  217. #endif
  218.  
  219. #ifdef THINKC3
  220. #define THINKC    1
  221. #define DOS_OR_T3 1
  222. #endif
  223.  
  224. #ifdef THINKC4
  225. #define THINKC    1
  226. #define ANSI    1
  227. #include <console.h>
  228. #endif
  229.  
  230. #ifdef VMS
  231. #define GOODEXIT    1
  232. int queued = -1;
  233. int dcl_chan = 0;
  234. #ifdef TIMEOUT
  235. #include <iodef.h>
  236. #include <descrip.h>
  237. struct ios_block {
  238.     short iostat,count;
  239.     int def_info;
  240. };
  241. #endif
  242. #else
  243. #define GOODEXIT    0
  244. #endif
  245.  
  246. #ifdef ANSI
  247. #include <stddef.h>
  248. #ifndef NO_STDLIB_H
  249. #include <stdlib.h>
  250. #endif
  251. #endif
  252.  
  253. #ifdef MSDOS
  254. #include <conio.h>
  255. #endif
  256.  
  257. #ifdef UNIX
  258. #include <errno.h>
  259. extern int errno;
  260. #include <fcntl.h>
  261. #include <sys/types.h>            /* these four are for kbhit() */
  262. #include <sys/time.h>
  263. #include <sys/uio.h>
  264. #include <sys/socket.h>
  265. #ifdef TIMEOUT
  266. #define UNOBLOCK 1
  267. #endif
  268. #endif
  269.  
  270. #ifdef UNOBLOCK
  271. #ifdef TERMIOS
  272. #include <sys/termios.h>
  273. typedef struct termios termstruct;
  274. #define GETTERM TCGETS
  275. #define SETTERM TCSETSF
  276. #endif
  277. #ifdef TERMIO
  278. #include <sys/termio.h>
  279. typedef struct termio termstruct;
  280. #define GETTERM TCGETA
  281. #define SETTERM TCSETAF
  282. #endif
  283. #ifdef TTY
  284.  
  285. #ifdef CRAY
  286. #include <sys/ioctl.h>
  287. #else
  288. #include <sgtty.h>    /* may need to be <ioctl.h> on some systems */
  289. #endif /* CRAY */
  290.  
  291. typedef struct sgttyb termstruct;
  292. static int one = 1;
  293. #define GETTERM TIOCGETP
  294. #define SETTERM TIOCSETP
  295. #endif
  296. #endif
  297.  
  298. #ifndef INTRCHAR
  299. #ifdef THINKC
  300. #define INTRCHAR    '.'
  301. #else
  302. #define INTRCHAR    3
  303. #endif
  304. #endif
  305.  
  306. /* local routines */
  307. static void bohelp(),bshelp();
  308. static char * ask();
  309. static int ready();
  310. static char * response();
  311. static void getreply();
  312. #ifdef TIMEOUT
  313. static void putnflush();
  314. static int termchar();
  315. #endif
  316. static void incorrect(),help(),showhist();
  317. void setnoblock(),resetterm();  /* used by control.c */
  318. #ifdef QUICKC
  319. static void sleep();
  320. #endif
  321.  
  322. /* standard #defines, and some more */
  323. #define MAXPLAYERS    20
  324. #define MAXROUNDS    20
  325. #define MAXPERIODS    5
  326. #define MAXTIMES    400
  327. #define MAXTOKENS    4    /* don't change */
  328. #define ROLES        3
  329. #define PLAYERNUMBER    9999    /* always use 9999 for human */
  330. #define EOS        '\0'
  331. #define BELL        07
  332. #define BS        010
  333. #define DEL        0177
  334. #define LINESIZE      82
  335.  
  336. /* local variables */
  337. int passflag = 0;        /* flag for p (pass) option */
  338. int fastflag = 0;        /* flag for f (fast) option */
  339. int waitflag = 0;        /* flaf for w (wait) option */
  340. int unwise=0;            /* flag for unwise mode */
  341. int yes = 0;            /* flag for yes mode */
  342. char linebuf[LINESIZE];        /* line buffer for I/O */
  343. char newline[] = "\n";
  344. char none[] = "\0";
  345. int timeleft = 0;        /* countdown timer */
  346.  
  347. /* the history list and associated variables and flag bits */
  348. #ifdef HISTORY
  349. unsigned int histlist[MAXHIST][MAXDISPLAY];
  350. int tlist[MAXHIST];
  351. int last = (-1);
  352. #define BUYCHAR '<'
  353. #define SELLCHAR '>'
  354. #define BOMASK  8191
  355. #define CURRENT    8192
  356. #define BFLAG    16384
  357. #define SFLAG    32768
  358. #define TIMEMASK    1023
  359. #define NOBOHIST    1024
  360. #define NOBSHIST    2048
  361. #endif
  362.  
  363.  
  364. /* auxiliary routines */
  365. void gbegin() {}
  366. void gend() {}
  367. void rbegin() {}
  368. void rend() {}
  369. void pend() {}
  370.  
  371. /* pbegin -- called at the start of each period */
  372. void
  373. pbegin()
  374. {
  375. #ifdef BEEP
  376.     putc(BELL,stderr);
  377.     fflush(stderr);
  378.     sleep(2);    /* just for aesthetics */
  379. #endif
  380.     passflag = 0;
  381. #ifdef HISTORY
  382.     last = (-1);    /* clear history list */
  383. #endif
  384. }
  385.  
  386.  
  387. /* boend -- called at the end of every bid-offer step */
  388. void
  389. boend()
  390. {
  391. #ifdef HISTORY
  392.     register int i;
  393.     int l;
  394.     unsigned int * hist;
  395. #endif
  396.  
  397.     if (bo == -2)
  398.     showcurrent();
  399. #ifdef HISTORY
  400.     l = ++last % MAXHIST;
  401.     if (bo == -2)
  402.     tlist[l] = NOBSHIST;    /* time unknown, no bs info yet */
  403.     else
  404.     tlist[l] = t|NOBSHIST;
  405.     hist = histlist[l];
  406.     for (i=1; i<=nbuyers; i++) {
  407.     hist[i-1] = bids[i];
  408.     if (i == bidder)
  409.         hist[i-1] |= CURRENT;
  410.     }
  411.     hist += nbuyers;
  412.     for (i=1; i<=nsellers; i++) {
  413.     hist[i-1] = offers[i];
  414.     if (i == offerer)
  415.         hist[i-1] |= CURRENT;
  416.     }
  417.     showhist(AUTOHIST);
  418. #endif
  419. #ifdef HEADLINE
  420.     twolinehead();
  421. #endif
  422. }
  423.  
  424.  
  425. /* bsend -- called at the end of every buy-sell step */
  426. void
  427. bsend()
  428. {
  429. #ifdef HISTORY
  430.     register int i;
  431.     unsigned int * hist;
  432.     int l;
  433.  
  434.     l = last % MAXHIST;
  435.     if (bs == -2) {        /* late */
  436.     l = ++last % MAXHIST;
  437.     tlist[l] = NOBOHIST;    /* time unknown, no bo info */
  438.     hist = histlist[l];
  439.     for (i=1; i<=nbuyers; i++)
  440.         hist[i-1] = 0;
  441.     for (i=1; i<=nsellers; i++)
  442.         hist[nbuyers+i-1] = 0;
  443.     if (bstype == 1) hist[nbuyers+seller-1] = price|CURRENT;
  444.     if (bstype == 2) hist[buyer-1] = price|CURRENT;
  445.     }
  446.     else
  447.     tlist[l] = (tlist[l]|t)&(~NOBSHIST);
  448.     hist = histlist[l];
  449.  
  450.     switch (bstype) {
  451.     case 1:
  452.     hist[buyer-1] |= BFLAG;
  453.     hist[nbuyers+seller-1] |= BFLAG;
  454.     break;
  455.     case 2:
  456.     hist[buyer-1] |= SFLAG;
  457.     hist[nbuyers+seller-1] |= SFLAG;
  458.     break;
  459.     default:
  460.     break;
  461.     }
  462.     showhist(AUTOHIST);
  463. #endif
  464. }
  465.  
  466.  
  467. /* bid -- called in every bid-offer step if we're playing a buyer.
  468.  *    Must return bid value or 0.  Must return 0 if nobidoff>0.
  469.  */
  470. int
  471. bid()
  472. {
  473.     int nexttoken;
  474.     int newbid;
  475.     char * reply;
  476.  
  477. #ifdef TIME_OUT_BO
  478.     timeleft = TIME_OUT_BO;
  479. #else
  480.     timeleft = timeout*2/3;
  481. #endif
  482.  
  483.     if (nobidoff>0) {
  484.     while (!ready("nothing to trade")) ;
  485.     return (0);
  486.     }
  487.     nexttoken = token[mytrades+1];
  488.  
  489.     while(1) {
  490.     if (cbid>=nexttoken-1 && unwise) {
  491.         if (ready("unwise to bid"))
  492.         return (0);
  493.         else
  494.         continue;
  495.     }
  496.     reply = ask("bid [n]");
  497.     if (*reply == EOS) continue;
  498.     if (*reply == '\n'|| *reply == 'n')
  499.         return (0);
  500.     if (sscanf(reply,"%d",&newbid) != 1) {
  501.         if (*reply != '?') incorrect(reply);
  502.         bohelp("bid");
  503.         continue;
  504.     }
  505.     if (newbid<minprice || newbid>maxprice)
  506.         printf("%cInvalid bid!\nYou must bid in the range %d-%d",
  507.         BELL,minprice,maxprice);
  508.     else if (newbid<=cbid)
  509.         printf("%cInvalid bid!\nYou must bid above the current bid of %d",
  510.         BELL,cbid);
  511.     else if (newbid>=nexttoken && unwise)
  512.         printf(
  513. "%cUnwise bid!\nYou should bid below your next token of %d",BELL,nexttoken);
  514.     else
  515.         return (newbid);
  516.     puts(", or press RETURN to pass.");
  517.     }
  518.     /*NOTREACHED*/
  519. }
  520.  
  521.  
  522. /* offer -- called in every bid-offer step if we're playing a seller.
  523.  *    Must return offer value or 0.  Must return 0 if nobidoff>0.
  524.  */
  525. int
  526. offer()
  527. {
  528.     int nexttoken;
  529.     int newoffer;
  530.     char * reply;
  531.  
  532. #ifdef TIME_OUT_BO
  533.     timeleft = TIME_OUT_BO;
  534. #else
  535.     timeleft = timeout*2/3;
  536. #endif
  537.  
  538.     if (nobidoff>0) {
  539.     while (!ready("nothing to trade")) ;
  540.     return (0);
  541.     }
  542.     nexttoken = token[mytrades+1];
  543.  
  544.     while(1) {
  545.     if (coffer>0 && coffer<=nexttoken+1 && unwise) {
  546.         if (ready("unwise to offer"))
  547.         return (0);
  548.         else
  549.         continue;
  550.     }
  551.     reply = ask("offer [n]");
  552.     if (*reply == EOS) continue;
  553.     if (*reply == '\n' || *reply == 'n')
  554.         return (0);
  555.     if (sscanf(reply,"%d",&newoffer) != 1) {
  556.         if (*reply != '?') incorrect(reply);
  557.         bohelp("offer");
  558.         continue;
  559.     }
  560.     if (newoffer == 0) return (0);
  561.     if (newoffer<minprice || newoffer>maxprice)
  562.         printf("%cInvalid offer!\nYou must offer in the range %d-%d",
  563.         BELL,minprice,maxprice);
  564.     else if (coffer>0 && newoffer>=coffer)
  565.         printf(
  566. "%cInvalid offer!\nYou must offer below the current offer of %d",
  567.         BELL,coffer);
  568.     else if (newoffer<=nexttoken && unwise)
  569.         printf(
  570. "%cUnwise offer!\nYou should offer above your next token of %d",BELL,nexttoken);
  571.     else
  572.         return (newoffer);
  573.     puts(", or press RETURN to pass.");
  574.     }
  575.     /*NOTREACHED*/
  576. }
  577.  
  578.  
  579. /* buy -- called in every buy-sell step if we're playing a buyer.
  580.       Must return 1 to request a buy, or 0 to pass.
  581.       Must return 0 if nobuysell>0. */
  582. int
  583. buy()
  584. {
  585.     int nexttoken;
  586.     char * reply;
  587.     char prompt[15];
  588.  
  589. #ifdef TIME_OUT_BS
  590.     timeleft = TIME_OUT_BS;
  591. #else
  592.     timeleft = timeout*2/3;
  593. #endif
  594.  
  595.     if (nobuysell&1) {
  596.     while (!ready("nothing to trade")) ;
  597.     return (0);
  598.     }
  599.     if (nobuysell&2) {
  600.     while (!ready("nothing to buy")) ;
  601.     return (0);
  602.     }
  603.     if (nobuysell&4) {
  604.     while (!ready("not bidder")) ;
  605.     return (0);
  606.     }
  607.     nexttoken = token[mytrades+1];
  608.     while(1) {
  609.     if (nexttoken<=coffer && unwise) {
  610.         if (ready("unwise to buy"))
  611.         return (0);
  612.         else
  613.         continue;
  614.     }
  615.     sprintf(prompt,"buy at %d [%c]",coffer,yes?'y':'n');
  616.     reply = ask(prompt);
  617.     if (*reply == EOS) continue;
  618.     if (*reply == '\n')
  619.         return (yes);
  620.     if (*reply == 'n')
  621.         return (0);
  622.     else if (*reply == 'y')
  623.         return (1);
  624.     else {
  625.         if (*reply != '?') incorrect(reply);
  626.         bshelp("buy the current offer");
  627.     }
  628.     } 
  629.     /*NOTREACHED*/
  630. }
  631.  
  632.  
  633. /* sell -- called in every buy-sell step if we're playing a seller.
  634.       Must return 1 to request a sell, or 0 to pass.
  635.       Must return 0 if nobuysell>0. */
  636. int
  637. sell()
  638. {
  639.     int nexttoken;
  640.     char * reply;
  641.     char prompt[15];
  642.  
  643. #ifdef TIME_OUT_BS
  644.     timeleft = TIME_OUT_BS;
  645. #else
  646.     timeleft = timeout*2/3;
  647. #endif
  648.  
  649.     if (nobuysell&1) {
  650.     while (!ready("nothing to trade")) ;
  651.     return (0);
  652.     }
  653.     if (nobuysell&2) {
  654.     while (!ready("nothing to sell")) ;
  655.     return (0);
  656.     }
  657.     if (nobuysell&4) {
  658.     while (!ready("not offerer")) ;
  659.     return (0);
  660.     }
  661.     nexttoken = token[mytrades+1];
  662.     while(1) {
  663.     if (nexttoken>=cbid && unwise) {
  664.         if (ready("unwise to sell"))
  665.         return (0);
  666.         else
  667.         continue;
  668.     }
  669.     sprintf(prompt,"sell at %d [%c]",cbid,yes?'y':'n');
  670.     reply = ask(prompt);
  671.     if (*reply == EOS) continue;
  672.     if (*reply == '\n')
  673.         return (yes);
  674.     if (*reply == 'n' || *reply == '0')
  675.         return (0);
  676.     else if (*reply == 'y' || *reply == '1')
  677.         return (1);
  678.     else {
  679.         if (*reply != '?') incorrect(reply);
  680.         bshelp("sell at the current bid value");
  681.     }
  682.     } 
  683.     /*NOTREACHED*/
  684. }
  685.  
  686.  
  687. /* --------- miscellaneous support routines for human interface --------- */
  688.  
  689. static void
  690. bohelp(string)
  691. char * string;
  692. {
  693.     printf("To make a%s %s, type your %s value.\n",(*string=='o')?"n":"",
  694.     string,string);
  695.     puts("To pass, type 'n' or just press RETURN.");
  696.     puts("Type 'help' for more information.\n");
  697. }
  698.  
  699.  
  700. static void
  701. bshelp(string)
  702. char * string;
  703. {
  704.     printf("Type 'y' to request to %s.\n",string);
  705.     puts("Type 'n' to pass.");
  706.     printf("Just pressing RETURN is presently equivalent to '%c'.\n",
  707.     yes?'y':'n');
  708.     puts("Type 'help' for more information.\n");
  709. }
  710.  
  711.  
  712. static char *
  713. ask(prompt)
  714. char *prompt;
  715. /*
  716.  * Asks 'prompt? ' and waits for reply or timeout.
  717.  * Includes processing of user commands.
  718.  * Returns reply string or "\n" if timeout.
  719.  */
  720. {
  721.     char tempchar;
  722.     waitforreturn = 0;
  723.  
  724.     if (passflag) {
  725.     if (kbhit()) {
  726.         tempchar = getchar();
  727.         if (tempchar == 'P' || tempchar == 'p') {
  728.         passflag = 0;
  729.         return response(prompt,1,0);
  730.         }
  731.     }
  732.     puts(prompt);
  733.     return newline;
  734.     }
  735.     return response(prompt,1,0);
  736. }
  737.  
  738.  
  739. static int
  740. ready(prompt)
  741. char * prompt;
  742. /*
  743.  * Says 'prompt> ' and waits for response or timeout.
  744.  * Includes processing of user commands.
  745.  * Returns 1 for correct reply/timeout, 0 for anything else.
  746.  */
  747. {
  748.     char * reply;
  749.  
  750.     waitforreturn = 0;
  751.  
  752.     if (fastflag || passflag) {
  753.     puts(prompt);
  754.     return 1;
  755.     }
  756.     reply = response(prompt,0,timeleft-5);
  757.     if (*reply == EOS) return 0;
  758.     if (*reply == '\n') return 1;
  759.     if (*reply != '?') incorrect(reply);
  760.     puts("A message ending in '>' is just informational.");
  761.     puts("Press RETURN to continue before the delay expires.");
  762.     puts(
  763. "You can prevent any wait at '>' prompts by setting the 'f' (fast) flag.");
  764.     puts("Type 'help' for more information.\n");
  765.     return 0;
  766. }
  767.  
  768.  
  769. static char *
  770. response(prompt,quest,stoptime)
  771. char *prompt;
  772. int quest;    /* 1 for ?, 0 for > */
  773. int stoptime;
  774. /*
  775.  * Writes prompt, gets reply or times out.
  776.  * Displays a . every second (or a : in the last five seconds) if DOTS.
  777.  * Processes options and user commands (e.h. 'help', 's').
  778.  * Returns user's reply (past any options) if any.
  779.  * Returns "\0" if no reply yet, but possible change of options etc.
  780.  * Returns '\n' if timeout occurs.
  781.  * Quits if reply is 'quit'.
  782.  */
  783. {
  784.     int done,value;
  785.     char * lptr;
  786.  
  787. /* put out the prompt */
  788.     fputs(prompt,stdout);
  789.     if (quest)
  790.     fputs("? ",stdout);
  791.     else
  792.     fputs("> ",stdout);
  793.     fflush(stdout);
  794.         
  795. /* get reply */
  796.     getreply(linebuf,LINESIZE,stoptime);
  797.  
  798. /* test for '\n', 'quit', 'help', literal quote */
  799.     if (linebuf[0] == '\n')
  800.     return linebuf;
  801.     if (strcmp(linebuf,"quit\n")==0)
  802.     error("");
  803.     if (strcmp(linebuf,"help\n")==0) {
  804.     help();
  805.     return none;
  806.     }
  807.     if (linebuf[0] == '\'') {
  808.     puts("Don't type the quotes (') themselves.");
  809.     return none;
  810.     }
  811.  
  812. /* process single letter options and commands */
  813.     lptr = linebuf;
  814.     value = 1;
  815.     done = 0;
  816.     do {
  817.     switch (*lptr++) {
  818.     case ' ':
  819.     case '\t':
  820.     case '\n':
  821.         break;
  822.     case '-':
  823.         value = 0;
  824.         break;
  825.     case '+':
  826.         value = 1;
  827.         break;
  828.     case 'a':
  829.         yes = value;
  830.         break;
  831.     case 'P':
  832.         passflag = value;
  833.         break;
  834.     case 'f':
  835.         fastflag = value;
  836.         break;
  837.     case 'u':
  838.         unwise = value;
  839.         break;
  840.     case 'w':
  841.         waitflag = value;
  842.         break;
  843.     case 's':
  844.     case 'c':
  845.     case 't':
  846.         showcurrent();
  847.         break;
  848.     case '$':
  849.     case 'p':
  850.         nl();
  851.         showprices();
  852.         break;
  853.     case 'h':
  854.         showhist(MAXHIST);
  855.         break;
  856.     default:
  857.         done++;
  858.     }
  859.     } while (!done) ;
  860.  
  861. /* return rest of string (EOS if none) */
  862.     return (--lptr);
  863. }
  864.  
  865.  
  866. static void
  867. getreply(buf,size,stoptime)
  868. char *buf;
  869. int size;
  870. int stoptime;
  871. /*
  872.  * Gets user's response, or times out.
  873.  * Puts out .'s or :'s.
  874.  * Deals with simple local editing (BS or DEL).
  875.  */
  876. {
  877. #ifdef TIMEOUT
  878.     register int c;
  879.     char * ptr;
  880. #endif
  881.  
  882. /* discard pending input */
  883. #ifdef UNIX
  884. #ifdef TTY
  885.     ioctl(fileno(stdin),TIOCFLUSH,&one);
  886. #else
  887.     ioctl(fileno(stdin),TCFLSH,0);
  888. #endif
  889. #endif
  890. #ifdef DOS_OR_T3
  891.     while (kbhit())
  892.     getch();
  893. #endif
  894. #ifdef THINKC4
  895.     fflush(stdin);
  896. #endif
  897. #ifdef VMS
  898.     queued = (-1);    /* only works if timeout enabled */
  899. #endif
  900.  
  901. #ifdef TIMEOUT
  902.     if (waitflag || timeout==9999) {
  903.     if (noblock)
  904.         resetterm();
  905.     fgets(buf,size,stdin);
  906.     return;
  907.     }
  908.  
  909.     if (!noblock)
  910.     setnoblock();
  911.  
  912.     if (stoptime<0) stoptime = 0;
  913.     ptr = buf;
  914.     while (1) {
  915.  
  916. /* sleep a second */
  917.     sleep(1);
  918.  
  919. /* read in available characters */
  920. #ifdef UNIX
  921.     errno = 0;
  922. #endif
  923.     while( (c = termchar()) != EOF && c != '\n'
  924. #ifdef THINKC
  925.           && c != '\r' && c != 3) {
  926. #else
  927.           && c != '\r') {
  928. #endif
  929.         if (c == INTRCHAR)
  930.         error("interrupt");
  931.         else if (c == BS || c == DEL) {
  932.         if (ptr > buf) {
  933.             if (c == DEL) {
  934.             putnflush(BS);
  935.             putnflush(BS);
  936.             }
  937.             putnflush(' ');
  938.             putnflush(BS);
  939.             --ptr;
  940.             ++size;
  941.         }
  942.         }
  943.         else if (size > 2) {
  944.         *(ptr++) = c;
  945.         --size;
  946.         }
  947.     }
  948.  
  949. /* message is complete if the last was \n or other terminator */
  950.     if (c != EOF)  {
  951.         if (c != '\n') putnflush('\n');
  952.         *(ptr++) = '\n';
  953.         *(ptr) = EOS;
  954.         return;
  955.     }
  956.  
  957. #ifdef UNIX
  958. /* check for unexpected error */
  959. #ifdef EAGAIN
  960.     if ( errno != 0 && errno != EWOULDBLOCK && errno != EAGAIN)  { 
  961. #else
  962.     if ( errno != 0 && errno != EWOULDBLOCK)  { 
  963. #endif
  964.         error("termchar failure");
  965.     }
  966. #endif
  967.  
  968. /* put out . or : if no characters yet and DOTS defined */
  969. #ifdef DOTS
  970.     if (ptr == buf) {
  971.         if (timeleft-stoptime>6)
  972.         putnflush('.');
  973.         else if (timeleft-stoptime>1)
  974.         putnflush(':');
  975.     }
  976. #endif
  977.  
  978. /* give up and return "\n" if timed out */
  979.     if (--timeleft <= stoptime) {
  980.         buf[0] = '\n';
  981.         buf[1] = EOS;
  982.         puts("!");
  983.         fflush(stdout);
  984.         return;
  985.     }
  986.     }
  987. #else
  988.     fgets(buf,size,stdin);
  989. #endif
  990. }
  991.  
  992.  
  993. #ifdef TIMEOUT
  994. static void
  995. putnflush(c)    /* puts out one character and flushes */
  996. int c;
  997. {
  998.     putchar(c);
  999.     fflush(stdout);
  1000. }
  1001.  
  1002.  
  1003. static int
  1004. termchar()
  1005. /*
  1006.  * Reads one character from the terminal if there is one,
  1007.  * otherwise returns EOF.
  1008.  */
  1009. {
  1010.     int c = EOF;
  1011. #ifdef UNIX
  1012.     char buf[1];
  1013.     if (read(0,buf,1) == 1)
  1014.     c = buf[0]&0177;
  1015. #endif
  1016. #ifdef DOS_OR_T3
  1017.     if (kbhit())
  1018.     c = getche();
  1019. #endif
  1020. #ifdef THINKC4
  1021.     c = getchar();
  1022.     if (c == EOF) c = getchar();
  1023.     if (c == EOF) c = getchar();
  1024.     if (c == EOF) c = getchar();
  1025.     if (c != EOF) putchar(c);    /* do our own echo -- CBREAK mode doesn't work */
  1026. #endif
  1027. #ifdef VMS
  1028.     static char buf[2];
  1029.     static struct ios_block iosb;
  1030.     if (queued<=0) {
  1031.     if (sys$qio(0,dcl_chan,
  1032.         IO$_READVBLK|IO$M_NOFILTR|((queued<0)?IO$M_PURGE:0),
  1033.         &iosb,0,0,buf,1,0,0,0,0) != 1) error("qio failure");
  1034.     queued = 1;
  1035.     }
  1036.     if (iosb.iostat == 1) {
  1037.     c = buf[0];
  1038.     queued = 0;
  1039.     }
  1040.     else if (iosb.iostat)
  1041.     error("i/o error");
  1042. #endif
  1043.     return c;
  1044. }
  1045. #endif
  1046.  
  1047.  
  1048. static void
  1049. incorrect(reply)    /* Puts out 'Incorrect response' message */
  1050. char * reply;
  1051. {
  1052.     printf("%c** Incorrect response: %s",BELL,reply);
  1053. }
  1054.  
  1055.  
  1056. static void
  1057. help()            /* Copies 'helpfile' to terminal */
  1058. {
  1059.     FILE * helpfile;
  1060.  
  1061.     helpfile = fopen("helpfile","r");
  1062.     if (helpfile == NULL) {
  1063.     puts("helpfile not available");
  1064.     return;
  1065.     }
  1066.     while(fgets(linebuf,LINESIZE,helpfile) != NULL)
  1067.     if (linebuf[0] != '#')
  1068.         fputs(linebuf,stdout);
  1069.     fclose(helpfile);
  1070. }
  1071.  
  1072.  
  1073. static void
  1074. showhist(nlines)    /* Display history of nlines recent steps in this period */
  1075. int nlines;
  1076. {
  1077. #ifndef HISTORY
  1078.     puts("history not available");
  1079. #else
  1080.     register int i,j,l;
  1081.     int ll;
  1082.     int tt;
  1083.     int anytrade;
  1084.     int prevcbid,prevcoffer,prevtt;
  1085.     unsigned int * hist;
  1086.     unsigned int code;
  1087.     char suffix[3];
  1088.     int tprice,lfirst,value;
  1089.  
  1090.     if (nlines <= 0) return;
  1091.     if (nlines >= MAXHIST) nlines = MAXHIST;
  1092.     
  1093.     if (last < 0) {
  1094.     puts("no history yet in this period");
  1095.     return;
  1096.     }
  1097.     printf("\nt   ");
  1098.     for (i=1; i<=nbuyers; i++)
  1099.     if (i == id && role == 1)
  1100.         fputs("  YOU  ",stdout);
  1101.     else
  1102.         printf("   B%d  ",i);
  1103.     for (i=1; i<=nsellers; i++)
  1104.     if (i == id && role == 2)
  1105.         fputs("  YOU  ",stdout);
  1106.     else
  1107.         printf("   S%d  ",i);
  1108.     puts(" price");
  1109.  
  1110.  
  1111.     lfirst = last+1-nlines;
  1112.     if (lfirst<0) lfirst = 0;
  1113.  
  1114.     prevcbid = 0;
  1115.     prevcoffer = 0;
  1116.     prevtt = 0;
  1117.     for (ll=lfirst; ll<=last; ll++) {
  1118.     l = ll%MAXHIST;
  1119.     hist = histlist[l];
  1120.     tt = tlist[l]&TIMEMASK;
  1121.     if (tt==0 && prevtt>0 && ll<last &&
  1122.         (tlist[(ll+1)%MAXHIST]&TIMEMASK)==prevtt+2) {
  1123.         tt = prevtt+1;
  1124.         tlist[l] |= tt;    /* fix  t/?/t+2  sequence */
  1125.     }
  1126.     if (tt > 0)
  1127.         printf("%-3d",tt);
  1128.     else
  1129.         fputs("?  ",stdout);
  1130.     if (tlist[l]&(NOBOHIST|NOBSHIST))
  1131.         putchar('*');
  1132.     else if (tt!=prevtt+1 && tt>0 && prevtt>0)
  1133.         putchar('!');
  1134.     else
  1135.         putchar(' ');
  1136.     prevtt = tt;
  1137.     tprice = 0;
  1138.     anytrade = 0;
  1139.     for (i=1; i<=nbuyers+nsellers; i++) {
  1140.         code = hist[i-1];
  1141.         value = (code&BOMASK);
  1142.         j = 0;
  1143.         if (code&CURRENT) {
  1144.         if (value == 0) {
  1145.             if (i<=nbuyers) value = prevcbid;
  1146.             else        value = prevcoffer;
  1147.             suffix[j++] = '#';
  1148.         }
  1149.         else {
  1150.             if (i<=nbuyers) prevcbid = value;
  1151.             else            prevcoffer = value;
  1152.             suffix[j++] = '*';
  1153.         }
  1154.         }
  1155.         if (code&SFLAG) {
  1156.         suffix[j++] = SELLCHAR;
  1157.         ++anytrade;
  1158.         }
  1159.         else if (code&BFLAG) {
  1160.         suffix[j++] = BUYCHAR;
  1161.         ++anytrade;
  1162.         }
  1163.         if (j==0) suffix[0] = ' ';
  1164.         if (j<=1) suffix[1] = ' ';
  1165.         suffix[2] = EOS;
  1166.         if (value > 0)
  1167.         printf("%5d%s",value,suffix);
  1168.         else
  1169.         printf("     %s",suffix);
  1170.         if (j==2) {
  1171.         if (i <= nbuyers)
  1172.             { if (code&SFLAG) tprice = value; }
  1173.         else
  1174.             { if (code&BFLAG) tprice = value; }
  1175.         }
  1176.     }
  1177.     if (tprice > 0)
  1178.         printf(" %5d\n",tprice);
  1179.     else if (anytrade)
  1180.         puts("    ?");
  1181.     else
  1182.         nl();
  1183.     }
  1184.     nl();
  1185. #endif
  1186. }
  1187.  
  1188.  
  1189. #ifdef FILEBASED
  1190. /* --------------------- save and restore routines ----------------------
  1191.  * The following two routines are used to save and restore the program's
  1192.  * variables between invocations if the FILEBASED method is used.
  1193.  */
  1194.  
  1195. extern FILE * savefile;
  1196.  
  1197. void
  1198. savedata()    /* write the save file */
  1199. {
  1200.     extern void writearray();
  1201. /* added for human interface */
  1202. #ifdef HISTORY
  1203.     register int i,j;
  1204.     int lastj;
  1205.     unsigned int * hist;
  1206. #endif
  1207.  
  1208.     fprintf(savefile,"%d %d %d %d %d %d %d %d %d\n",
  1209.     nplayers,nbuyers,nsellers,nrounds,nperiods,ntimes,
  1210.     minprice,maxprice,gameid);
  1211.     fprintf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
  1212.     r,p,t,cbid,coffer,bidder,offerer,nbids,noffers,bstype,
  1213.     price,buyer,seller,ntrades,lasttime);
  1214.     fprintf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d\n",
  1215.     id,role,timeout,ntokens,mytrades,mylasttime,pprofit,
  1216.     rprofit,gprofit,nobidoff,bo,nobuysell,bs,late,noblock);
  1217.     writearray(bnumber,nbuyers);
  1218.     writearray(snumber,nsellers);
  1219.     writearray(bids,nbuyers);
  1220.     writearray(offers,nsellers);
  1221.     writearray(btrades,nbuyers);
  1222.     writearray(strades,nsellers);
  1223.     writearray(prices,ntrades);
  1224.     writearray(token,ntokens);
  1225.     writearray(tradelist,p);
  1226.     writearray(profitlist,p);
  1227. /* added for human interface */
  1228.     fprintf(savefile,"%d %d %d %d %d\n",unwise,yes,passflag,fastflag,waitflag);
  1229. #ifdef HISTORY
  1230.     fprintf(savefile,"%d\n",last);
  1231.     if (last>=MAXHIST)    lastj = MAXHIST-1;
  1232.     else        lastj = last;
  1233.     for (j=0; j<=lastj; j++) {
  1234.     hist = histlist[j];
  1235.     fprintf(savefile,"%d ",tlist[j]);
  1236.     for (i=0; i<nbuyers+nsellers; i++)
  1237.         fprintf(savefile,"%u ",hist[i]);
  1238.     putc('\n',savefile);
  1239.     }
  1240. #endif
  1241.  
  1242. }
  1243.  
  1244.  
  1245. void
  1246. retrievedata()    /* read the save file */
  1247. {
  1248.     extern void readarray();
  1249. /* added for human interface */
  1250. #ifdef HISTORY
  1251.     register int i,j;
  1252.     int lastj;
  1253.     unsigned int * hist;
  1254. #endif
  1255.  
  1256.     fscanf(savefile,"%d %d %d %d %d %d %d %d %d",
  1257.     &nplayers,&nbuyers,&nsellers,&nrounds,&nperiods,&ntimes,
  1258.     &minprice,&maxprice,&gameid);
  1259.     fscanf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
  1260.     &r,&p,&t,&cbid,&coffer,&bidder,&offerer,&nbids,&noffers,&bstype,
  1261.     &price,&buyer,&seller,&ntrades,&lasttime);
  1262.     fscanf(savefile,"%d %d %d %d %d %d %d %d %d %d %d %d %d %d %d",
  1263.     &id,&role,&timeout,&ntokens,&mytrades,&mylasttime,&pprofit,
  1264.     &rprofit,&gprofit,&nobidoff,&bo,&nobuysell,&bs,&late,&noblock);
  1265.     readarray(bnumber,nbuyers);
  1266.     readarray(snumber,nsellers);
  1267.     readarray(bids,nbuyers);
  1268.     readarray(offers,nsellers);
  1269.     readarray(btrades,nbuyers);
  1270.     readarray(strades,nsellers);
  1271.     readarray(prices,ntrades);
  1272.     readarray(token,ntokens);
  1273.     readarray(tradelist,p);
  1274.     readarray(profitlist,p);
  1275. /* added for human interface */
  1276.     fscanf(savefile,"%d %d %d %d %d\n",&unwise,&yes,&passflag,&fastflag,
  1277.     &waitflag);
  1278. #ifdef HISTORY
  1279.     fscanf(savefile,"%d",&last);
  1280.     if (last>=MAXHIST)    lastj = MAXHIST-1;
  1281.     else        lastj = last;
  1282.     for (j=0; j<=lastj; j++) {
  1283.     hist = histlist[j];
  1284.     fscanf(savefile,"%d ",tlist+j);
  1285.     for (i=0; i<nbuyers+nsellers; i++)
  1286.         fscanf(savefile,"%u ",hist+i);
  1287.     }
  1288. #endif
  1289. }
  1290. #endif
  1291.  
  1292.  
  1293. /* get user's limits etc */
  1294. void
  1295. getparams(maxplayers,maxrounds,maxperiods,maxtimes,maxtokens,roles,playernum)
  1296. int *maxplayers, *maxrounds, *maxperiods, *maxtimes, *maxtokens;
  1297. int *roles, *playernum;
  1298. {
  1299.     *maxplayers = MAXPLAYERS;
  1300.     *maxrounds = MAXROUNDS;
  1301.     *maxperiods = MAXPERIODS;
  1302.     *maxtimes = MAXTIMES;
  1303.     *maxtokens = MAXTOKENS;
  1304.     *roles = ROLES;
  1305.     *playernum = PLAYERNUMBER;
  1306. }
  1307.  
  1308.  
  1309. /* ------------- pre-game routines for INETBASED case ------------- */
  1310. #ifdef INETBASED
  1311. void
  1312. getpname(name,maxlen)
  1313. char *name;
  1314. int maxlen;
  1315. /*
  1316.  * Get player name.
  1317.  * Asks user for name, copies it into name with trailing \n\0.
  1318.  */
  1319. {
  1320.     int len;
  1321.  
  1322.     do {
  1323.     fputs("Enter your name: ",stderr);
  1324.     if (fgets(linebuf,LINESIZE,stdin) == NULL)
  1325.         error("read failed (try 'reset')");
  1326.     if (strcmp(linebuf,"quit\n")==0)
  1327.         exit(GOODEXIT);
  1328.     len = strlen(linebuf);
  1329.     if (len >= maxlen) {
  1330.         fputs("** too long -- shorten\n",stderr);
  1331.         len = 0;
  1332.     }
  1333.     } while (len <= 1) ;
  1334.     strcpy(name,linebuf);
  1335. }
  1336.  
  1337. void
  1338. getpassword(password,maxlen)
  1339. char *password;
  1340. int maxlen;
  1341. {
  1342.     int len;
  1343.     char linebuf[200];
  1344.  
  1345.     do {
  1346.     fputs("Please enter your password: ",stderr);
  1347.     if (fgets(linebuf,LINESIZE,stdin) == NULL)
  1348.         error("read failed (try 'reset')");
  1349.     if (strcmp(linebuf,"quit\n")==0)
  1350.         exit(0);
  1351.     len = strlen(linebuf);
  1352.     if (len >= maxlen-1) {
  1353.         fputs("** too long -- shorten\n",stderr);
  1354.         len = 0;
  1355.     }
  1356.     } while (len <= 1);
  1357.     sprintf(password, "#%s",linebuf);
  1358.  
  1359. }
  1360.  
  1361. int
  1362. getrole()
  1363. {
  1364.     return 3;
  1365. }
  1366. #endif
  1367.  
  1368.  
  1369. /*
  1370.  * Routines for non-blocking terminal input.  These put the terminal
  1371.  * in a non-standard state, but try hard to restore the old state
  1372.  * before exit or abort.  If the program is killed or aborted by
  1373.  * other than ^C the changed state may remain; use the Unix 'reset'
  1374.  * command to fix it (if the shell doesn't log you out!).
  1375.  * Specifically the terminal should be made to:
  1376.  *    1. Not block if there are no characters available.
  1377.  *    2. Return individual characters as soon as available.
  1378.  *    3. Not process erase or kill characters (implied by 2).
  1379.  *    4. Echo control charaacters as is, not as ^x.
  1380.  *    5. Not recognize ^C as an interrupt.
  1381.  * Note that there are three different Unix ways of doing this.  All
  1382.  * are implemented here, and are selected by defining TTY, TERMIO, or
  1383.  * TERMIOS depending on the system.  See the #define's near the start
  1384.  * of this file.
  1385.  *    TTY    Old unix terminal handler.
  1386.  *    TERMIO    System V standard, and some others.
  1387.  *    TERMIOS    New BSD handler.
  1388.  * Also note that FCNTL is needed on some systems to implement no-blocking.
  1389.  */
  1390.  
  1391. #ifdef UNOBLOCK
  1392. static int save1,save2,save3;
  1393. termstruct mytermios;
  1394. #ifdef TTY
  1395. struct tchars spchars;
  1396. static int lmode;
  1397. #endif
  1398. #endif
  1399.  
  1400.  
  1401. void
  1402. setnoblock()    /* set up terminal for non-blocking input */
  1403. {
  1404. #ifdef UNOBLOCK
  1405.     int fdin = fileno(stdin);
  1406. #ifdef FCNTL
  1407.     fcntl(fdin,F_SETFL,O_NDELAY);    /* no block */
  1408. #endif
  1409.     ioctl(fdin,GETTERM,&mytermios);
  1410. #ifdef TTY
  1411.     save1 = mytermios.sg_flags;
  1412.     mytermios.sg_flags |= CBREAK;    /* no input processing */
  1413. #else
  1414.     save1 = mytermios.c_lflag;
  1415.     save2 = mytermios.c_cc[VMIN];
  1416.     save3 = mytermios.c_cc[VTIME];
  1417.     mytermios.c_lflag = ECHO;        /* no canon, no signals */
  1418.     mytermios.c_cc[VMIN] = 0;        /* MIN = 0 */
  1419.     mytermios.c_cc[VTIME] = 0;        /* TIME = 0 */
  1420. #endif
  1421.     ioctl(fdin,SETTERM,&mytermios);
  1422. #ifdef TTY
  1423.     ioctl(fdin,TIOCGETC,&spchars);
  1424.     save2 = spchars.t_intrc;
  1425.     spchars.t_intrc = '\377';        /* no interrupt */
  1426.     ioctl(fdin,TIOCSETC,&spchars);
  1427.     ioctl(fdin,TIOCLGET,&save3);
  1428.     lmode = save3&~LCTLECH;        /* no ^x echo */
  1429.     ioctl(fdin,TIOCLSET,&lmode);
  1430. #endif
  1431. #endif
  1432. #ifdef THINKC4
  1433.     csetmode(C_RAW,stdin);
  1434. #endif
  1435. #ifdef VMS
  1436. #ifdef TIMEOUT
  1437.     static $DESCRIPTOR(ttyname,"SYS$INPUT");
  1438.     if (sys$assign(&ttyname,&dcl_chan,0,0) != 1)
  1439.     error("can't assign SYS$INPUT");
  1440. #endif
  1441. #endif
  1442.     noblock = 1;
  1443. }
  1444.  
  1445.  
  1446. void
  1447. resetterm()    /* restore previous terminal state */
  1448. {
  1449. #ifdef UNOBLOCK
  1450.     int fdin = fileno(stdin);
  1451.     ioctl(fdin,GETTERM,&mytermios);
  1452. #ifdef TTY
  1453.     mytermios.sg_flags = save1;
  1454. #else
  1455.     mytermios.c_lflag = save1;
  1456.     mytermios.c_cc[VMIN] = save2;
  1457.     mytermios.c_cc[VTIME] = save3;
  1458. #endif
  1459.     ioctl(fdin,SETTERM,&mytermios);
  1460. #ifdef TTY
  1461.     ioctl(fdin,TIOCGETC,&spchars);
  1462.     spchars.t_intrc = save2;
  1463.     ioctl(fdin,TIOCSETC,&spchars);
  1464.     ioctl(fdin,TIOCLSET,&save3);
  1465. #endif
  1466. #ifdef FCNTL
  1467.     fcntl(fdin,F_SETFL,0);
  1468. #endif
  1469. #endif
  1470. #ifdef THINKC4
  1471.     csetmode(C_ECHO,stdin);
  1472. #endif
  1473.     noblock = 0;
  1474. }
  1475.  
  1476.  
  1477. #ifdef QUICKC
  1478. static void
  1479. sleep(secs)    /* sleep() routine for QUICKC */
  1480. int secs;
  1481. {
  1482.  
  1483.     long start,end,ltime;
  1484.     start = time(<ime);
  1485.     end = start + secs;
  1486.     do {;} while(time(<ime)<end);
  1487.  
  1488. }
  1489. #endif
  1490.  
  1491. #ifdef UNIX
  1492. /* For BSD 4.2 compatibility */
  1493. #ifndef FD_ZERO
  1494. typedef struct fd_set_tag {
  1495.         long masks[9];
  1496. } DESCR_MASK;
  1497. #define FD_SET(n, p)   ((p)->masks[(n) / 32] |=  (1 << ((n) % 32)))
  1498. #define FD_CLR(n, p)   ((p)->masks[(n) / 32] &= ~(1 << ((n) % 32)))
  1499. #define FD_ISSET(n, p) ((p)->masks[(n) / 32] &   (1 << ((n) % 32)))
  1500. #define FD_ZERO(p)     bzero((p), sizeof(*(p)))
  1501. #else
  1502. typedef fd_set DESCR_MASK;
  1503. #endif
  1504.  
  1505. int input_waiting(fd)
  1506.         int fd;
  1507. {
  1508.         struct timeval tv;
  1509.         DESCR_MASK readers;
  1510.  
  1511.         tv.tv_sec = tv.tv_usec = 0;
  1512.         FD_ZERO(&readers);
  1513.         FD_SET(fd, &readers);
  1514.         return select(fd + 1, &readers, (DESCR_MASK *) NULL,
  1515.                       (DESCR_MASK *) NULL, &tv);
  1516. }
  1517.  
  1518. int kbhit() { return input_waiting(0); }
  1519. #endif        /* UNIX */
  1520.  
  1521.